import React, { PureComponent, createRef } from 'react'
import {
  Card,
  Form,
  Input,
  Cascader,
  Button,
  Icon,
  message,
  Popover,
} from 'antd'
import { LinkButton } from '../../components/link-button'
import {
  reqCategorys,
  reqAddOrUpdateProduct,
  reqFindSameTitle,
} from '../../api'
import PicturesWall from './pictures-wall'
import Editor from './editor'
import { getReqData } from '../../utils'
import { connect } from 'react-redux'

const { Item } = Form

class ProductAddUpdate extends PureComponent {
  constructor(props) {
    super(props)

    this.isUpdate = false // 是否是修改的标识。如果点击了“修改”按钮，就是true
    this.product = {}

    // 创建保存ref标识的标签对象的容器
    // 存储的是 PicturesWall 的对象
    // 使用 this.pw.current 访问 PicturesWall 中的 getImgs() 方法
    this.pw = createRef()
    this.richTextEditor = createRef()
    // 级联中点击分类得到的文字
    this.cascaderText = ''
    this.input = createRef()
  }

  state = {
    options: [],
    inputOnChangeContent: [],
    // 点击标题的提示框后返回的图片存储在这里。
    selectedTitleImgs: [],
  }

  /**
   * 级联中的加载数据
   * @param selectedOptions this.state.options的其中一项
   */
  loadData = async (selectedOptions) => {
    const targetOption = selectedOptions[selectedOptions.length - 1]
    targetOption.loading = true

    // 得到二级分类列表
    let subCategories = await this.getCategorys(targetOption.value)
    targetOption.loading = false

    if (subCategories && subCategories.length > 0) {
      // 生成一个二级列表的options
      // 关联到当前option上
      targetOption.children = subCategories.map((item) =>
        // 这个label就是种类的名字
        ({ value: item._id, label: item.name, isLeaf: true })
      )
    } else {
      // 当前页面中的分类不是二级分类
      targetOption.isLeaf = true
    }

    // 如果是这样，那么使用 PureComponent 是不会更新的。
    // 但是实际上再点击一次就能够显示 商品分类 界面了。
    // this.setState({options: this.state.options});

    // 使用这样，才会让 PureComponent 更新。因为值的地址已经发生改变了。
    // 如果使用状态对象修改状态，那么需要使用三点运算符生成新的值。
    // 否则不会渲染。

    // 这里的 this.state.options 是什么时候修改的？
    // 就是前面的所有操作修改的，写得太隐晦了！
    // console.log('this.state.options', this.state.options);
    this.setState({ options: [...this.state.options] })
  }

  /**
   * 点击选择级联
   */
  onChange = (value, selectedOptions) =>
    (this.cascaderText = selectedOptions.map((o) => o.label).join('/'))

  /**
   * 点击选择 装修种类的 级联
   */
  onChangeDecorationType = (value, selectedOptions) =>
    (this.cascaderTextDecorationType = selectedOptions
      .map((o) => o.label)
      .join('/'))

  /**
   * 这里返回的是标题对应的信息
   */
  inputOnChangeResult = () => {
    const { inputOnChangeContent } = this.state
    if (!inputOnChangeContent) return <span>没有数据</span>
    const result = inputOnChangeContent.map((item) => (
      <Button
        type="none"
        key={item._id}
        onClick={() => this.selectTitle(item.imgs)}
      >
        {item.title}
      </Button>
    ))
    return inputOnChangeContent.length === 0 ? <span>没有数据</span> : result
  }

  /**
   * 实时监测标题输入框的内容，匹配相同标题下的封面图片
   */
  getInputValue = async () => {
    let { value } = this.input.current.props
    if (!value) return
    value = value.replace(/\s+/g, '') // 去除空格
    if (value === '') return
    const result = await reqFindSameTitle(value)
    const data = getReqData(result)
    if (!data || data.length === 0) return null

    // todo 返回的数据中，如果有title和输入的完全相同，则警告标题重复。
    // todo 尝试使用  “Notification通知提醒框”
    // todo 或者使用form表单的本身的验证提醒。

    this.setState({ inputOnChangeContent: data })
  }

  /**
   * 点击标题，显示这个文章的封面。
   */
  selectTitle = (imgs) => {
    // 查询已经上传的图片。
    // console.log('selectTitle', imgs);
    if (imgs.length === 0) return
    this.setState({ selectedTitleImgs: imgs })
  }

  /**
   * 提交的回调函数
   */
  submit = () => {
    // 表单验证通过才发送请求。
    this.props.form.validateFields(async (error, values) => {
      if (!error) {
        // 1 收集数据封装成product对象。结构中的数据来自于 getFieldDecorator('categoryIds', {}) 等。
        let { title, categoryIds, decorationTypeIds } = values
        let pCategoryId, categoryId

        title = title || '无'

        if (1 === categoryIds.length) {
          pCategoryId = '0'
          categoryId = categoryIds[0]
        } else {
          pCategoryId = categoryIds[0]
          categoryId = categoryIds[1]
        }

        const imgs = this.pw.current.getImgs()

        // 这里是指“文章”
        const detail = this.richTextEditor.current.getDetail()
        const articleText = this.richTextEditor.current.getText()

        let product = {
          title, // 标题
          imgs, // 这里是，图片上传成功后，在云存储中的位置所组成的数组。
          article: detail, // 文章
          articleText, // 不带html的文本，用于显示在index页面等。
          categoryId, // 所属分类id
          pCategoryId, // 父级分类id
          cascaderText: this.cascaderText, // 当前级联选择得到的种类文字。显示的时候不用再根据id请求了。
          decorationTypeInfo: {
            pCategoryId: decorationTypeIds[0],
            categoryId: decorationTypeIds[1],
            cascaderText: this.cascaderTextDecorationType,
          },
        }

        if (this.isUpdate) product._id = this.product._id

        console.log(product)

        // 2 调用请求接口函数添加/更新
        const { result } = await reqAddOrUpdateProduct(product)

        // 3 根据结果提示
        const tempMsg = this.isUpdate ? '更新' : '添加'
        const flag = getReqData(result)

        if (!flag) {
          message.error(`${tempMsg}失败`)
        } else {
          message.success(`${tempMsg}成功`)
          this.props.history.goBack()
        }
      }
    })
  }

  /**
   * 根据categorys生成options数组
   * 更新状态
   * @param categorys 异步获取的数据
   */
  initOptions = async (categorys) => {
    let options = categorys.map((item) => ({
      label: item.name,
      value: item._id,
      isLeaf: false,
    }))

    const { pCategoryId } = this.product
    // 如果更新二级分类列表中的数据
    if (this.isUpdate && pCategoryId !== '0') {
      // 获取二级列表
      let subCategorys = await this.getCategorys(pCategoryId)
      // 生成二级下拉菜单的options
      let childOptions = subCategorys.map((c) => ({
        value: c._id,
        label: c.name,
        isLeaf: true,
      }))
      // 找到当前商品对应的一级option对象
      let targetOption = options.find((option) => option.value === pCategoryId)
      // 关联到对应的一级option上
      targetOption.children = childOptions
    }

    // 找到 装修种类 这部分数据
    const decorationParentId = '5df0e327cdaeae3670403134'
    const decorationOptions = await this.getExtendOption(
      options,
      decorationParentId
    )

    // 找到 其他 这部分的数据
    const otherParentId = '5df2097206c387360c5c29a0'
    const otherOptions = await this.getExtendOption(options, otherParentId)

    // 从 options 中清理出 装修种类+其他 这部分数据
    options = options.filter(
      (item) =>
        item.value !== decorationParentId && item.value !== otherParentId
    )

    this.setState({ options, extendOption: [decorationOptions, otherOptions] })
  }

  /**
   * 获取 扩展的选项 比如标签
   */
  getExtendOption = async (options, id) => {
    const otherParentId = id
    const otherOptions = options.find((item) => item.value === otherParentId)
    let subOthers = await this.getCategorys(otherParentId)
    otherOptions.children = subOthers.map((c) => ({
      value: c._id,
      label: c.name,
      isLeaf: true,
    }))
    return otherOptions
  }

  /**
   * 异步获取一级/二级分类列表
   * 更新options
   */
  getCategorys = async (parentId) => {
    const { result } = await reqCategorys(parentId)
    const data = getReqData(result)

    if (!data) {
      message.error(result.data.msg)
      return null
    }

    // 如果是一级分类列表
    if (0 === parentId * 1) this.initOptions(data)
    // 如果是二级列表
    else {
      return data
    }
  }

  UNSAFE_componentWillMount() {
    //  如果使用哈希路由，传递的参数在这里是获取不到的。
    // 在下面才能获取。
    if (this.props.product) {
      // console.log('this.props.product UNSAFE_componentWillMount', this.props.product);
      this.isUpdate = true
      this.product = this.props.product
      this.cascaderText = this.product.cascaderText
    }
  }

  componentDidMount() {
    this.getCategorys('0')
  }

  componentWillUnmount() {
    // 这里有一个bug，如果修改的时候，刷新页面，那么就会无限循环
    if (!this.props.product) return null
  }

  render() {
    const { options, extendOption, selectedTitleImgs } = this.state
    const {
      pCategoryId,
      categoryId,
      imgs,
      article,
      decorationTypeInfo,
    } = this.product

    // 显示商品的级联。这个用于初始化。
    // 这里的id会自动和this.state.options对应
    const categoryIds = []
    if (this.isUpdate) {
      // 如果是二级分类
      if (pCategoryId !== '0') {
        categoryIds.push(pCategoryId)
        categoryIds.push(categoryId)
      } else {
        // 如果是一级分类
        categoryIds.push(categoryId)
      }
    }

    // 初始化装修种类
    const categoryIdsDecoration = []
    if (this.isUpdate && decorationTypeInfo) {
      categoryIdsDecoration.push(decorationTypeInfo.pCategoryId)
      categoryIdsDecoration.push(decorationTypeInfo.categoryId)
    }
    const title = (
      <span>
        <LinkButton onClick={() => this.props.history.goBack()}>
          {/*这里的icon大小，是使用fontsize控制的*/}
          <Icon type="arrow-left" style={{ fontSize: 20 }} />
        </LinkButton>
        <span>{this.isUpdate ? '修改' : '添加'}图片/文章</span>
      </span>
    )
    // 指定item布局的宽度比例
    const formItemLayout = {
      labelCol: { span: 2 }, // 左侧label的宽度
      wrapperCol: { span: 8 }, // 右侧的宽度
    }
    const { getFieldDecorator } = this.props.form
    return (
      <Card title={title}>
        <Form {...formItemLayout}>
          <Item label="标题">
            {getFieldDecorator('title', {
              initialValue: this.product.title,
              rules: [{ required: true, message: '必须输入标题' }],
            })(
              <Input
                ref={this.input}
                initialValue={this.product.title}
                placeholder="请输入"
              />
            )}
          </Item>
          <Item label="匹配">
            <Popover
              title="匹配结果"
              content={this.inputOnChangeResult()}
              placement="right"
              trigger="click"
            >
              <Button onClick={this.getInputValue}>
                尝试匹配类似标题的文章，点击按钮后将使用这篇文章的封面。
              </Button>
            </Popover>
          </Item>
          <Item label="封面图片">
            <PicturesWall
              ref={this.pw}
              id={this.product._id + ''}
              imgs={imgs && imgs.length > 0 ? imgs : selectedTitleImgs}
              max={5}
            />
          </Item>
          {/*这里的指定很重要，总共默认分为24份。这里设定总共22份*/}
          {/*{*/}
          {/*labelCol: {span: 2}, // 左侧label的宽度*/}
          {/*wrapperCol: {span: 8}, // 右侧的宽度*/}
          {/*}*/}
          <Item label="文章" labelCol={{ span: 2 }} wrapperCol={{ span: 20 }}>
            {/*<RichTextEditor ref={this.richTextEditor} detail={article}/>*/}
            <Editor ref={this.richTextEditor} detail={article} />
          </Item>
          <Item label="所属分类">
            {getFieldDecorator('categoryIds', {
              initialValue: categoryIds,
              rules: [{ required: true, message: '必须选择所属分类' }],
            })(
              <Cascader
                options={options}
                loadData={this.loadData}
                placeholder="请选择所属分类"
                onChange={this.onChange}
                changeOnSelect
              />
            )}
          </Item>
          <Item label="所属标签">
            {getFieldDecorator('decorationTypeIds', {
              initialValue: categoryIdsDecoration,
            })(
              <Cascader
                options={extendOption}
                loadData={this.loadData}
                placeholder="请选择所属标签"
                onChange={this.onChangeDecorationType}
                changeOnSelect
              />
            )}
          </Item>
          <Item>
            {/*这里不用onsubmit，那么就不会提交表单。如果使用onsubmit那么需要阻止默认行为。*/}
            <Button type="primary" onClick={this.submit}>
              提交
            </Button>
          </Item>
        </Form>
      </Card>
    )
  }
}

export default connect(
  (state) => ({ product: state.hashRouteParams }),
  null
)(Form.create()(ProductAddUpdate))
